#pragma once
template <typename Type = int>
class DynArray
{
private:
	unsigned int currentsize;
	unsigned int cap;
	Type *dynarray;
public:
	DynArray();
	~DynArray();
	DynArray(const DynArray<Type>& that);
	DynArray<Type>& operator=(const DynArray<Type>& that);
	Type&operator[](const unsigned int index);
	const Type& operator[](const unsigned int index) const;
	unsigned int size() const;
	unsigned int capacity() const;
	void clear();
	void append(const Type& item);
	void reserve(const unsigned int & newCap = 0);

};
template <typename Type>
DynArray<Type>::DynArray()
{
	dynarray = new Type[0];
	currentsize = 0;
	cap = 0;
}

template <typename Type>
DynArray<Type>::~DynArray()
{
	delete [] dynarray;
}

template <typename Type>
DynArray<Type>::DynArray(const DynArray<Type>& that)
{
	dynarray = nullptr;
	dynarray = new Type[that.cap];
	currentsize = that.currentsize;
	cap = that.cap;
	for(decltype(currentsize) i = 0; i < currentsize; i++)
		dynarray[i] = that.dynarray[i];
}

template <typename Type>
DynArray<Type>& DynArray<Type>::operator=(const DynArray<Type>& that)
{
	if(&that != this)
	{
		delete [] dynarray;
		dynarray = nullptr;
		dynarray = new Type[that.cap];
		currentsize = that.currentsize;
		cap = that.cap;
		for(decltype(currentsize) i = 0; i < currentsize; i++)
			dynarray[i] = that.dynarray[i];
	}
	return *this;
}

template <typename Type>
Type& DynArray<Type>::operator[](const unsigned int index)
{
	return dynarray[index];
}

template <typename Type>
const Type& DynArray<Type>::operator[](const unsigned int index) const
{
	return dynarray[index];
}

template <typename Type>
unsigned int DynArray<Type>::size() const
{
	return currentsize;
}

template <typename Type>
unsigned int DynArray<Type>::capacity() const
{
	return cap;
}

template <typename Type>
void DynArray<Type>::clear()
{
	cap = 0;
	currentsize = 0;
}

template <typename Type>
void DynArray<Type>::append(const Type& item)
{
	if(cap == 0)
	{
		cap += 1;
		Type *temp = new Type[1];
		temp[0] = item;
		delete [] dynarray;
		dynarray = temp;
		currentsize +=1;
	}
	else if(cap == currentsize)
	{
		cap = cap * 2;
		Type *temp = new Type[cap];
		for(decltype(currentsize) i = 0; i < currentsize; i++)
			temp[i] = dynarray[i];
		delete [] dynarray;
		temp[currentsize] = item;
		dynarray = temp;
		currentsize += 1;
	}
	else
	{
		Type *temp = new Type[cap];
		for(decltype(currentsize) i = 0; i < currentsize; i++)
			temp[i] = dynarray[i];
		delete [] dynarray;
		temp[currentsize] = item;
		dynarray = temp;
		currentsize += 1;
	}


}

template <typename Type>
void DynArray<Type>::reserve(const unsigned int & newCap = 0)
{
	if(newCap == 0)
		if(cap == 0)
		{
			cap += 1;
			Type *temp = new Type[cap];
			for(decltype(currentsize) i = 0; i < currentsize; i++)
				temp[i] = dynarray[i];
			delete [] dynarray;
			dynarray = temp;
		}
		else
		{
			cap = cap * 2;
			Type *temp = new Type[cap];
			for(decltype(currentsize) i = 0; i < currentsize; i++)
				temp[i] = dynarray[i];
			delete [] dynarray;
			dynarray = temp;
		}
	else if(newCap <= cap)
		return;
	else
	{
		cap = newCap;
		Type *temp = new Type[cap];
		for(decltype(currentsize) i = 0; i < currentsize; i++)
			temp[i] = dynarray[i];
		delete [] dynarray;
		dynarray = temp;
	}
}

